using Microsoft.EntityFrameworkCore;
using UniversalAdminSystem.Domian.Core.ValueObjects;
using UniversalAdminSystem.Domian.PermissionManagement.Aggregate;
using UniversalAdminSystem.Domian.PermissionManagement.ValueObjects;
using UniversalAdminSystem.Domian.UserManagement.Aggregates;
using UniversalAdminSystem.Domian.UserManagement.Entities;
using UniversalAdminSystem.Domian.UserManagement.ValueObj;
using UniversalAdminSystem.Domian.LogManagement.Aggregates;
using UniversalAdminSystem.Domian.SystemSettings.Aggregates;
using UniversalAdminSystem.Domian.SystemSettings.ValueObjects;
using UniversalAdminSystem.Domian.FileStorage.ValueObjects;
using File = UniversalAdminSystem.Domian.FileStorage.Aggregates.File;
using UniversalAdminSystem.Domian.knowledge.Aggregates;
using System.Data.Common;
using UniversalAdminSystem.Domian.knowledge.ValueObj;
using NpgsqlTypes;
using Pgvector;
using UniversalAdminSystem.Domian.UserConversations.Aggregates;
using UniversalAdminSystem.Infrastructure.RabbitMQ.Jobs;

namespace UniversalAdminSystem.Infrastructure.Persistence.DbContexts;

public class UniversalAdminSystemDbContext : DbContext
{
    public UniversalAdminSystemDbContext(DbContextOptions<UniversalAdminSystemDbContext> options) : base(options) { }

    public DbSet<UserInfo> UserInfos { get; set; }
    public DbSet<User> Users { get; set; }
    public DbSet<Role> Roles { get; set; }
    public DbSet<Permission> Permissions { get; set; }
    public DbSet<LogEntry> LogEntries { get; set; }
    public DbSet<SystemSetting> SystemSettings { get; set; }
    public DbSet<File> Files { get; set; }
    public DbSet<Conversations> Conversations { get; set; }
    public DbSet<Message> Messages { get; set; }
    public DbSet<DocumentChunk> Chunks { get; set; } 
    public DbSet<FileProcessingJob> FileProcessingJobs { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // 启用"vector"扩展
        modelBuilder.HasPostgresExtension("vector");

        // 配置UserInfo实体
        modelBuilder.Entity<UserInfo>(entity =>
        {
            entity.HasKey(u => u.UserInfoId);
            entity.Property(u => u.UserInfoId)
                .HasConversion(
                    id => id.Value,
                    value => UserInfoId.Create(value)
                );
        });

        // 配置User实体
        modelBuilder.Entity<User>(entity =>
        {
            entity.HasKey(u => u.UserId);
            entity.HasIndex(u => u.Account).IsUnique();

            // 配置UserId值对象转换
            entity.Property(u => u.UserId)
                .HasConversion(
                    id => id.Value,
                    value => UserId.Create(value)
                );

            // 配置UserInfoId值对象转换
            entity.Property(u => u.UserInfoId)
                .HasConversion(
                    id => id!.Value,
                    value => UserInfoId.Create(value)
                );

            // 配置UserEmail值对象转换
            entity.Property(u => u.Email)
                .HasConversion(
                    email => email.Value,
                    value => UserEmail.Create(value)
                );

            // 配置UserAccount值对象转换
            entity.Property(u => u.Account)
                .HasConversion(
                    account => account.Value,
                    value => UserAccount.Create(value)
                );

            // 配置User和Role的一对多关系
            entity.HasOne<Role>()
                .WithMany()
                .HasForeignKey("RoleId")
                .IsRequired(false)
                .OnDelete(DeleteBehavior.SetNull);
        });

        // 配置Permission实体
        modelBuilder.Entity<Permission>(entity =>
        {
            entity.HasKey(p => p.PermissionId);
            entity.HasIndex(p => p.Code).IsUnique();
            entity.Property(p => p.Code).HasConversion(
                code => code.Value,
                value => PermissionCode.Create(value)
            );
            entity.Property(p => p.Name).HasConversion(
                name => name.Value,
                value => PermissionName.Create(value)
            );

            entity.Property(p => p.Code).HasConversion(
                code => code.Value,
                value => PermissionCode.Create(value)
            );

            entity.Property(p => p.Resource).HasConversion(
                resource => resource.Value,
                value => PermissionResource.Create(value)
            );
        });

        // 配置Role
        modelBuilder.Entity<Role>(entity =>
        {
            entity.HasKey(r => r.RoleId);
            entity.HasIndex(r => r.Name).IsUnique();

            // 配置RoleId值对象转换
            entity.Property(r => r.RoleId)
                .HasConversion(
                    id => id.Value,
                    value => RoleId.Create(value)
                );

            // 配置RoleName值对象转换
            entity.Property(r => r.Name)
                .HasConversion(
                    name => name.Value,
                    value => RoleName.Create(value)
                );

            // 配置RoleDescription值对象转换
            entity.Property(r => r.Description)
                .HasConversion(
                    desc => desc!.Value,
                    value => RoleDescription.Create(value)
                );

            // 配置多对多关系
            entity.HasMany(r => r.Permissions)
                .WithMany()
                .UsingEntity(
                    "RolePermissions",
                    l => l.HasOne(typeof(Permission)).WithMany().HasForeignKey("PermissionId"),
                    r => r.HasOne(typeof(Role)).WithMany().HasForeignKey("RoleId"),
                    j =>
                    {
                        j.HasKey("RoleId", "PermissionId");
                        j.HasIndex("RoleId");
                        j.HasIndex("PermissionId");
                    }
                );
        });

        // 配置LogEntry实体
        modelBuilder.Entity<LogEntry>(entity =>
        {
            entity.HasKey(l => l.Id);
            entity.Property(l => l.UserId)
                .HasConversion(
                    userId => userId!.Value,
                    value => UserId.Create(value)
                );
        });

        // 配置SystemSetting实体
        modelBuilder.Entity<SystemSetting>(entity =>
        {
            entity.HasKey(s => s.Id);
            entity.Property(s => s.Key)
                .HasConversion(
                    key => key.Value,
                    value => SettingKey.Create(value)
                );
            entity.Property(s => s.Value)
                .HasConversion(
                    value => value.Value,
                    val => SettingValue.Create(val)
                );
            entity.Property(s => s.Description)
                .HasConversion(
                    desc => desc!.Value,
                    value => SettingDescription.Create(value)
                );
        });

        // 配置File实体
        modelBuilder.Entity<File>(entity =>
        {
            entity.HasKey(f => f.Id);
            entity.Property(f => f.Id)
                .HasConversion(
                    id => id.Value,
                    value => FileId.Create(value)
                );
            entity.Property(f => f.Name)
                .HasConversion(
                    name => name.Value,
                    value => FileName.Create(value)
                );
            entity.Property(f => f.Path)
                .HasConversion(
                    path => path.Value,
                    value => FilePath.Create(value)
                );
            entity.Property(f => f.Size)
                .HasConversion(
                    size => size.Value,
                    value => FileSize.Create(value)
                );
            entity.Property(f => f.Type)
                .HasConversion(
                    type => type.Value,
                    value => FileType.Create(value)
                );
            entity.Property(f => f.OwnerId)
                .HasConversion(
                    ownerId => ownerId.Value,
                    value => UserId.Create(value)
                );
            entity.Property(f => f.ParentId)
                .HasConversion(
                    parentId => parentId!.Value,
                    value => FileId.Create(value)
                );
        });

        modelBuilder.Entity<DocumentChunk>(entity =>
        {
            entity.HasKey(d => d.Id);
            

            entity.Property(d => d.FileId)
                .HasConversion(
                    fileId => fileId.Value,
                    value => FileId.Create(value)
                );

            entity.Property(d => d.Id)
                .HasConversion(id => id.Value,
                value => ChunkId.Create(value));

            entity.Property(d => d.Embedding)
                .HasColumnType("vector(1024)") 
                .HasConversion(
                    embedding => new Vector(embedding.Value),
                    value => TextEmbedding.Create(value.ToArray())
                );

        });

        modelBuilder.Entity<Conversations>(entity =>
        {
            entity.HasKey(c => c.Id);

            entity.Property(c => c.Id)
                .HasConversion(id => id.Value,
                value => ConversationId.Create(value)
                );

            entity.Property(c => c.UserId)
                .HasConversion(userid => userid.Value,
                value => UserId.Create(value)
                );

        });

        modelBuilder.Entity<Message>(entity =>
        {
            entity.HasKey(m => m.Id);

            entity.Property(m => m.Id)
                .HasConversion(id => id.Value,
                value => MessageId.Create(value)
                );

            entity.Property(m => m.ConversationId)
                .HasConversion(Conversationid => Conversationid.Value,
                value => ConversationId.Create(value)
                );
        });

        modelBuilder.Entity<FileProcessingJob>(entity =>
        {
            entity.HasKey(fpje => fpje.Id);
            entity.HasIndex(fpje => new { fpje.Status, fpje.NextAttemptAt, fpje.CreatedAt });
            entity.Property(fpje => fpje.Status).HasMaxLength(32);
        });

        // 忽略值对象
        modelBuilder.Ignore<RoleId>();
    }
}